Cplex callback
q```
…
// install a "lazyconstraint" callback to cut infeasible integer sol.s (found e.g. by heuristics)
CPXLONG contextid = CPX_CALLBACKCONTEXT_CANDIDATE; // ... means lazyconstraints
if ( CPXcallbacksetfunc(env, lp, contextid, my_callback, inst) ) print_error("CPXcallbacksetfunc() error");
//CPXsetintparam(env, CPX_PARAM_THREADS, 1); // just for debugging
...
CPXmipopt(env,lp); // with the callback installed
//CPXgetx(...); // optimal TSP sol. (or just feasible if time limit...), if any
...
static int CPXPUBLIC my_callback(CPXCALLBACKCONTEXTptr context, CPXLONG contextid, void userhandle){
instance inst = (instance) userhandle;
double xstar = (double) malloc(inst->ncols sizeof(double));
double objval = CPX_INFBOUND;
if ( CPXcallbackgetcandidatepoint(context, xstar, 0, inst->ncols-1, &objval) ) print_error("CPXcallbackgetcandidatepoint error");
// get some random information at the node (as an example for the students)
int mythread = -1; CPXcallbackgetinfoint(context, CPXCALLBACKINFO_THREADID, &mythread);
int mynode = -1; CPXcallbackgetinfoint(context, CPXCALLBACKINFO_NODECOUNT, &mynode);
double incumbent = CPX_INFBOUND; CPXcallbackgetinfodbl(context, CPXCALLBACKINFO_BEST_SOL, &incumbent);
//if ( VERBOSE >= 100 ) printf(" ... callback at node %5d thread %2d incumbent %10.2lf, candidate value %10.2lf\n", .....);
...
int nnz = 0;
... if xstart is infeasible, find a violated cut and store it in the usual Cplex's data structute (rhs, sense, nnz, index and value)
if ( nnz > 0 ) // means that the solution is infeasible and a violated cut has been found
{
int izero = 0;
if ( CPXcallbackrejectcandidate(context, 1, nnz, &rhs, &sense, &izero, index, value) ) print_error("CPXcallbackrejectcandidate() error"); // reject the solution and adds one cut
//if ( CPXcallbackrejectcandidate(context, 0, NULL, NULL, NULL, NULL, NULL, NULL) ) print_error("CPXcallbackrejectcandidate() error"); // just reject the solution without adding cuts (less effective)
}
free(xstar);
return 0;
}
...
CPXLONG contextid = CPX_CALLBACKCONTEXT_CANDIDATE | CPX_CALLBACKCONTEXT_RELAXATION; // both lazy and usercuts
if ( CPXcallbacksetfunc(env, lp, contextid, my_callback, inst) ) print_error("CPXcallbacksetfunc() error");
...
CPXmipopt(env,lp); // with the callback installed
...
/****/
static int CPXPUBLIC my_callback(CPXCALLBACKCONTEXTptr context, CPXLONG contextid, void userhandle )
/****/
{
instance inst = (instance*) userhandle;
double* xstar = (double*) malloc(inst->ncols * sizeof(double));
double objval = CPX_INFBOUND;
if ( contextid == CPX_CALLBACKCONTEXT_CANDIDATE && CPXcallbackgetcandidatepoint(context, xstar, 0, inst->ncols-1, &objval) ) print_error("CPXcallbackgetcandidatepoint error");
if ( contextid == CPX_CALLBACKCONTEXT_RELAXATION && CPXcallbackgetrelaxationpoint(context, xstar, 0, inst->ncols-1, &objval) ) print_error("CPXcallbackgetrelaxationpoint error");
if ( ... )
{
...
int izero = 0;
int purgeable = CPX_USECUT_FILTER;
int local = 0;
if ( contextid == CPX_CALLBACKCONTEXT_CANDIDATE && CPXcallbackrejectcandidate(context, 1, nnz, &rhs, &sense, &izero, cutind, cutval) ) print_error("CPXcallbackrejectcandidate() error"); // reject the solution and add one cut
if ( contextid == CPX_CALLBACKCONTEXT_RELAXATION && CPXcallbackaddusercuts(context, 1, nnz, &rhs, &sense, &izero, cutind, cutval,&purgeable, &local) ) print_error("CPXcallbackaddusercuts() error"); // add one violated usercut
}
...
free(xstar);
return 0;
}
/****/
static int CPXPUBLIC my_callback(CPXCALLBACKCONTEXTptr context, CPXLONG contextid, void userhandle )
/****/
{
instance inst = (instance*) userhandle;
if ( contextid == CPX_CALLBACKCONTEXT_CANDIDATE ) return my_callback_candidate(context, inst);
if ( contextid == CPX_CALLBACKCONTEXT_RELAXATION ) return my_callback_relaxation(context, inst);
print_error("contextid unknownn in my_callback");
return 1;
}
double *xheu = (double *) calloc(inst->ncols, sizeof(double)); // all zeros, initially
for ( int i = 0; i < inst->nnodes; i++ ) xheu[xpos(i,succ[i],inst)] = 1.0;
...
free(xheu);
int *ind = (int *) malloc(inst->ncols * sizeof(int));
for ( int j = 0; j < inst->ncols; j++ ) ind[j] = j;
int effortlevel = CPX_MIPSTART_NOCHECK;
int beg = 0;
if ( CPXaddmipstarts(env, lp, 1, inst->ncols, &beg, indices, xheu, &effortlevel, NULL) print_error("CPXaddmipstarts() error");
free(ind);
... starting from the integer xstar, use the patching heuristic + 2-opt to build a heuristic TSP solution xheu[0..ncols-1] of value objheu, and "post it" so CPLEX can use it
int *ind = (int *) malloc(inst->ncols * sizeof(int));
for ( int j = 0; j < inst->ncols; j++ ) ind[j] = j;
if ( CPXcallbackpostheursoln(context, inst->ncols, ind, xheu, objheu, CPXCALLBACKSOLUTION_NOCHECK) ) print_error("CPXcallbackpostheursoln() error");
free(ind);
void add_sec( CPXCENVptr env, CPXLPptr lp, Contextid Cid, const unsigned int nnodes,const int ncomp,const int* comp)